package com.dhcc.bpm.modules.scf.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dhcc.bpm.common.segmentId.LocalCacheIdGenerator;
import com.dhcc.bpm.modules.scf.dto.ScfRecyclingInInfoDTO;
import com.dhcc.bpm.modules.scf.entity.ScfOperationLogInfo;
import com.dhcc.bpm.modules.scf.entity.ScfRecyclingInInfo;
import com.dhcc.bpm.modules.scf.entity.SelectEntity.RecyclingInByPayment;
import com.dhcc.bpm.modules.scf.enumUtil.ScfOperationLogInfoEnum;
import com.dhcc.bpm.modules.scf.mapper.*;
import com.dhcc.bpm.modules.scf.service.IScfFileAttachmentInfoService;
import com.dhcc.bpm.modules.scf.service.IScfOperationLogInfoService;
import com.dhcc.bpm.modules.scf.service.IScfRecyclingInInfoService;
import com.dhcc.bpm.modules.scf.service.IScfSalesDetailsInfoService;
import com.dhcc.bpm.modules.scf.util.ExcelUtil;
import com.dhcc.bpm.modules.scf.util.MD5Utils;
import com.dhcc.bpm.modules.scf.util.OBSUtil;
import com.dhcc.bpm.modules.scf.vo.ScfContractInfoVO.ScfGetContractDetailsVO;
import com.dhcc.bpm.modules.scf.vo.ScfDriverInfoVO.ScfGetDriverDetailsVO;
import com.dhcc.bpm.modules.scf.vo.ScfFileAttachmentInfoVO.ScfFileAttachmentInfoVO;
import com.dhcc.bpm.modules.scf.vo.ScfRecyclingInInfoVO.ScfGetRecyclingInDetailsVO;
import com.dhcc.bpm.modules.scf.vo.ScfRecyclingInInfoVO.ScfGetRecyclingInListVO;
import com.dhcc.bpm.modules.scf.vo.ScfRecyclingWeighInfoVO.ScfGetRecyclingWeighDetailsVO;
import com.dhcc.bpm.modules.scf.vo.ScfRenewableInInfoVO.ScfGetRenewableInListVO;
import com.dhcc.bpm.modules.scf.vo.ScfSubjectBasicInfoVO.ScfGetSubjectDetailsVO;
import com.dhcc.bpm.modules.system.service.IUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


/**
 * 利废企业入库服务层接口实现类
 */
@Service
@Slf4j
public class ScfRecyclingInInfoServiceImpl extends ServiceImpl<ScfRecyclingInInfoMapper, ScfRecyclingInInfo> implements IScfRecyclingInInfoService {

    /**
     * 文件附件service接口
     */
    @Autowired
    private IScfFileAttachmentInfoService scfFileAttachmentInfoService;
    /**
     * id生成器
     */
    @Autowired
    private LocalCacheIdGenerator localCacheIdGenerator;
    /**
     * 合同信息mapper接口
     */
    @Autowired
    private ScfContractInfoMapper scfContractInfoMapper;
    /**
     * 主体信息mapper接口
     */
    @Autowired
    private ScfSubjectBasicInfoMapper scfSubjectBasicInfoMapper;
    /**
     * 支付信息mapper接口
     */
    @Autowired
    private ScfPaymentInfoMapper scfPaymentInfoMapper;
    /**
     * 司机信息mapper接口
     */
    @Autowired
    private ScfDriverInfoMapper scfDriverInfoMapper;
    /**
     * 操作记录service接口
     */
    @Autowired
    private IScfOperationLogInfoService scfOperationLogInfoService;
    /**
     * 利废企业过磅单mapper接口
     */
    @Autowired
    private ScfRecyclingWeighInfoMapper scfRecyclingWeighInfoMapper;
    /**
     * 销售信息service接口
     */
    @Autowired
    private IScfSalesDetailsInfoService scfSalesDetailsInfoService;
    /**
     * 销售信息mapper接口
     */
    @Autowired
    private ScfSalesDetailsInfoMapper scfSalesDetailsInfoMapper;
    /**
     * 用户信息service接口
     */
    @Autowired
    private IUserService userService;
    /**
     * 华为obs对象存储工具类
     */
    @Autowired
    private OBSUtil obsUtil;



    /**
     * 利废企业入库自定义分页查询
     *
     * @param page
     * @param scfRecyclingInInfo
     * @return
     */
    @Override
    public IPage<ScfGetRecyclingInListVO> selectScfRecyclingInInfoPage(IPage<ScfGetRecyclingInListVO> page, ScfRecyclingInInfoDTO scfRecyclingInInfo) {
        // 获取利废企业入库分页数据
        List<ScfGetRecyclingInListVO> scfGetRecyclingInListVOS = baseMapper.selectScfRecyclingInInfoPage(page, scfRecyclingInInfo);
        // 判断分页数据是否为空
        if (scfGetRecyclingInListVOS.size() != 0) {
            // 不为空，则遍历分页数据
            for (ScfGetRecyclingInListVO scfGetRecyclingInListVO : scfGetRecyclingInListVOS) {
                // 获取登记人字段中的用户id，查询用户信息接口查询出对应的名称并重新设置登记人字段
                List<Long> ids = new ArrayList<>();
                ids.add(Long.valueOf(scfGetRecyclingInListVO.getRecorder()));
                List<String> recorders = userService.selectUserNameByIds(ids);
                if (recorders !=null  && ! recorders.isEmpty()){
                    scfGetRecyclingInListVO.setRecorder(recorders.get(0));
                }

          /*      if(scfGetRecyclingInListVO.getSettlementAmount().compareTo( scfGetRecyclingInListVO.getPaidAmount() ) >0 ){
                    scfGetRecyclingInListVO.setPaySts("1");
                }
                if(scfGetRecyclingInListVO.getSettlementAmount().compareTo( scfGetRecyclingInListVO.getPaidAmount() )==0 ){
                    scfGetRecyclingInListVO.setPaySts("2");
                }
                if (scfGetRecyclingInListVO.getPaidAmount().compareTo(BigDecimal.ZERO) == 0) {
                    scfGetRecyclingInListVO.setPaySts("0");
                }*/
            }
        }
        return page.setRecords(scfGetRecyclingInListVOS);
    }

    /**
     * 利废企业入库自定义详情查询
     *
     * @param scfRecyclingInInfo
     * @return
     */
    @Override
    public ScfGetRecyclingInDetailsVO getDetails(ScfRecyclingInInfoDTO scfRecyclingInInfo) {
        ScfGetRecyclingInDetailsVO detail = baseMapper.getDetails(scfRecyclingInInfo.getRowId());
        if (detail != null) {
            // 获取与文件附件表关联的id
            String rowId = detail.getRowId();
            // 根据根据合同编号获取合同rowId
            String contractRowId = scfContractInfoMapper.selectRowIdByContractNum(detail.getContractNum() ,detail.getOrgCode());
            // 获取合同详细信息
            ScfGetContractDetailsVO detailsContract = scfContractInfoMapper.getDetails(contractRowId);
            // 从合同中获取再生及供应商主体编号并查询主体信息
            ScfGetSubjectDetailsVO scfSubjectBasicInfoMapperDetailsRenewable = scfSubjectBasicInfoMapper.getDetails(detailsContract.getPartyANum());
            if(scfSubjectBasicInfoMapperDetailsRenewable!=null ){
                // 从主体信息中拿到主体名称并赋值
                detail.setRenewableName(scfSubjectBasicInfoMapperDetailsRenewable.getSubName());
            }
            ScfGetSubjectDetailsVO scfSubjectBasicInfoMapperDetailsSupplierName = scfSubjectBasicInfoMapper.getDetails(detailsContract.getPartyBNum());
            if(scfSubjectBasicInfoMapperDetailsSupplierName !=null ){
                detail.setRecyclingName(scfSubjectBasicInfoMapperDetailsSupplierName.getSubName());
            }


            // 司机驾驶证号再去查询司机的详细信息
            String driverRowId = scfDriverInfoMapper.selectRowIdByLicense(detail.getLicense());
            if(driverRowId !=null ){
                ScfGetDriverDetailsVO scfDriverInfoMapperDetails = scfDriverInfoMapper.getDetails(driverRowId);
                // 取出司机姓名及司机联系方式并设置给入库单详情中
                detail.setDriverName(scfDriverInfoMapperDetails.getDriverName());
                detail.setDriverMobile(scfDriverInfoMapperDetails.getMobile());
            }


            // 查询利废入库与支付回单的关联关系并设置
            List<RecyclingInByPayment> recyclingInByPayments = baseMapper.selectRecyclingByPayment(detail.getRecyclingInNum());
            for (RecyclingInByPayment recyclingInByPayment : recyclingInByPayments) {
                // 根据支付回单号查询支付回单的剩余金额
                BigDecimal amount1 = scfPaymentInfoMapper.selectLfrkRemainAmountByPaymentNum(recyclingInByPayment.getPaymentNum());
                // 设置剩余金额  amount1.subtract(  recyclingInByPayment.getUseAmount() )
                recyclingInByPayment.setRemainAmount(amount1);
                recyclingInByPayment.setLfrkRemainAmount( recyclingInByPayment.getRemainAmount() );
            }
            // 利废入库单详情信息设置关联关系记录
            detail.setRecyclingInByPayments(recyclingInByPayments);
            // 设置利废过磅单数据
            // 获取过磅单号
            String weighNum = detail.getWeighNum();
            // 创建一个利废过磅单详情对象集合
            List<ScfGetRecyclingWeighDetailsVO> scfGetRecyclingWeighDetailsVOS = new ArrayList<>();
            // 如果可以获取到利废过磅单号
            if (weighNum != null) {
                // 查询出过磅单号对应的过磅rowId
                String rowIdByWeighNum = scfRecyclingWeighInfoMapper.getRowIdByWeighNum(weighNum);
                // 获取对应的过磅单详情信息
                ScfGetRecyclingWeighDetailsVO details = scfRecyclingWeighInfoMapper.getDetails(rowIdByWeighNum);
                // 添加到过磅单详情对象集合中
                scfGetRecyclingWeighDetailsVOS.add(details);
            }
            // 利废入库单详情信息设置利废过磅单信息
            detail.setScfGetRecyclingWeighDetailsVO(scfGetRecyclingWeighDetailsVOS);
            // 查询关联的附件信息
            List<ScfFileAttachmentInfoVO> scfFileAttachmentInfoVOS = scfFileAttachmentInfoService.selectAllByAssociationId(rowId);
            // 将附件信息存进dto里
            detail.setFileAttachmentInfoVOS(scfFileAttachmentInfoVOS);
        }
        return detail;
    }

    /**
     * 利废企业入库新增
     *
     * @param scfRecyclingInInfo
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean saveRecyclingInInfo(ScfRecyclingInInfoDTO scfRecyclingInInfo) throws Exception {
        // 判断是否已存在该入库单号码
        String recyclingInNum = scfRecyclingInInfo.getRecyclingInNum();
        String selectRowIdByRecyclingInNum = baseMapper.selectRowIdByRecyclingInNum(recyclingInNum);
        if (selectRowIdByRecyclingInNum != null) {
            // 说明该入库单号码库中存在，抛出异常，提示该入库单号码已存在
            throw new Exception("利废入库单:" + recyclingInNum + "已存在，请勿重复录入利废企业入库单！");
        }
        // 生成日期
        SimpleDateFormat date = new SimpleDateFormat("YYYYMMdd");
        String formatdate = date.format(new Date());
        // 生成时间
        SimpleDateFormat timeFormat = new SimpleDateFormat("HHmmss");
        String formTime = timeFormat.format(new Date());

        // 开始补充对象字段start
        // 设置默认支付状态为0.未支付
        scfRecyclingInInfo.setPaySts("0");
        // 设置默认已付金额为0
        scfRecyclingInInfo.setPaidAmount(BigDecimal.valueOf(0));
        // 获取关联的过磅单rowId
        String rowIdByWeighNum = scfRecyclingWeighInfoMapper.getRowIdByWeighNum(scfRecyclingInInfo.getWeighNum());
        // 如果关联的过磅单号不为空
        if (rowIdByWeighNum != null) {
            // 获取过磅单详情
            ScfGetRecyclingWeighDetailsVO weightDetails = scfRecyclingWeighInfoMapper.getDetails(rowIdByWeighNum);
            // 给利废企业入库单设置利废企业过磅单中的供销合同编号
            scfRecyclingInInfo.setContractNum(weightDetails.getContractNum());
            // 给利废企业入库单设置利废企业过磅单中的车牌号
            scfRecyclingInInfo.setTruckNum(weightDetails.getTruckNum());
            // 给利废企业入库单设置利废企业过磅单中的驾驶证证件号
            scfRecyclingInInfo.setLicense(weightDetails.getLicense());
        }
        // 设置记录编号
        String rowId = "LFRK" + MD5Utils.md5(  scfRecyclingInInfo.getRecyclingInNum());
        scfRecyclingInInfo.setRowId(rowId);
        // 设置登记日期
        scfRecyclingInInfo.setRecordDate(formatdate);
        // 设置登记时间
        scfRecyclingInInfo.setRecordTime(formTime);
        // 设置初始已付金额为0
        scfRecyclingInInfo.setPaidAmount(new BigDecimal("0"));
        // 补充对象字段结束end
        // 开始关联支付回单
        List<RecyclingInByPayment> recyclingInByPayments = scfRecyclingInInfo.getRecyclingInByPayments();
        if (recyclingInByPayments != null) {
            // 获取支付回单关联的信息
            for (RecyclingInByPayment recyclingInByPayment : recyclingInByPayments) {
                if (recyclingInByPayment.getUseAmount() == null) {
                    throw new NullPointerException("使用金额不能为空！");
                }
                // 获取当前支付回单的当前剩余金额
                BigDecimal remainAmountByPaymentNum = scfPaymentInfoMapper.selectAmountByPaymentNum(recyclingInByPayment.getPaymentNum());
                // 判断输入的使用金额是否大于当前剩余金额
                if (recyclingInByPayment.getUseAmount().compareTo(remainAmountByPaymentNum) > 0) {
                    throw new IllegalArgumentException("输入的使用金额大于支付回单剩余金额，请重新输入！");
                }
                // 设置利废入库单号码
                recyclingInByPayment.setRecyclingInNum(scfRecyclingInInfo.getRecyclingInNum());
                // 设置利废入库单编号rowId
                recyclingInByPayment.setRecyclingInRowId(scfRecyclingInInfo.getRowId());
                // 设置支付回单的编号RowId
                recyclingInByPayment.setPaymentRowId(recyclingInByPayment.getRowId());
                // 设置支付回单关联关系的rowId
                recyclingInByPayment.setRowId(   "LFRK" + MD5Utils.md5(scfRecyclingInInfo.getRowId() + recyclingInByPayment.getPaymentNum()  ) );
                recyclingInByPayment.setOrgCode(scfRecyclingInInfo.getOrgCode() );
                // 获取回单使用金额
                BigDecimal useAmount = recyclingInByPayment.getUseAmount();
                // 获取初始已付金额
                BigDecimal paidAmountInit = scfRecyclingInInfo.getPaidAmount();
                // 将回单使用金额加初始已付金额运算后设置进再生入库单的已付金额中
                // 将 useAmount 和 paidAmountInit 相加
                BigDecimal totalPaidAmount = paidAmountInit.add(useAmount);
                // 设置新的已付金额
                scfRecyclingInInfo.setPaidAmount(totalPaidAmount);
                // 获取利废企业入库单的已付金额
                BigDecimal paidAmount = scfRecyclingInInfo.getPaidAmount();
                // 获取利废企业入库的总金额
                BigDecimal amount = scfRecyclingInInfo.getAmount();
                // 初始化支付状态，默认为暂未支付
                String paymentStatus = "0";
                // 判断支付状态
                if (paidAmount.compareTo(BigDecimal.ZERO) > 0) {
                    if (paidAmount.compareTo(amount) < 0) {
                        // 如果已付小于总额，则设置为部分支付
                        paymentStatus = "1";
                    } else if (paidAmount.compareTo(amount) == 0) {
                        // 如果已付等于总额，则设置为全部支付
                        paymentStatus = "2";
                    } else if (totalPaidAmount.compareTo(amount) > 0) {
                        // 如果已付金额大于入库单金额，则抛出异常
                        throw new RuntimeException("支付回单输入的使用金额超过入库单金额！");
                    }
                    // 如果已付总额等于0，保持为暂未支付
                }
                // 保存关联关系
                baseMapper.saveRecyclingByPayment(recyclingInByPayment);
                // 将支付状态设置到再生资源入库单
                scfRecyclingInInfo.setPaySts(paymentStatus);
                // 将上一步获取到的金额加上新使用的金额
                // 将 remainAmountByPaymentNum 和 useAmount 相减
                BigDecimal totalAmount = remainAmountByPaymentNum.subtract(useAmount);

                // 获取支付回单的总面值
                BigDecimal amountByPaymentNum = scfPaymentInfoMapper.selectAmountByPaymentNum(recyclingInByPayment.getPaymentNum());
                // 判断
                String usageStatus;
                // 使用 compareTo 方法比较剩余金额和回单金额的大小关系
                int comparisonResult = totalAmount.compareTo(amountByPaymentNum);

                if (comparisonResult == 0) {
                    // 如果剩余金额等于回单金额，则设置为暂未使用
                    usageStatus = "0";
                } else if (comparisonResult < 0 && totalAmount.compareTo(BigDecimal.ZERO) != 0) {
                    // 如果剩余金额小于回单金额并大于0，则设置为部分使用
                    usageStatus = "1";
                } else {
                    // 如果剩余金额等于0，则设置为全部使用
                    usageStatus = "2";
                }
                // 同步更新对应回单的剩余金额及支付状态
                scfPaymentInfoMapper.updateRemainAmountAndSseStsLfrkRemainAmount(recyclingInByPayment.getPaymentNum(), totalAmount, usageStatus);
            }
        }
        boolean isSave = save(scfRecyclingInInfo);
        List<String> rowIds = scfRecyclingInInfo.getRowIds();
        // 设置合同文件存放路径
        String path = "RCRK" + "/" + rowId + "/";
        if (rowId != null) {
            if (!rowIds.isEmpty()) {
                // 取消旧文件与记录关联
                scfFileAttachmentInfoService.updataFiledNull(rowId);
                if (rowIds.size() != 0) {
                    // 给上传的新文件添加关联编号
                    scfFileAttachmentInfoService.batchUpdateField(rowIds, rowId);
                    for (String fileRowId : rowIds) {
                        // 根据文件id获取文件的临时objectKey
                        String objectKeyOfTemp = scfFileAttachmentInfoService.getFilePath(fileRowId,null);
                        // 截取文件的名称
                        String extractFileName = obsUtil.extractFileName(objectKeyOfTemp);
                        // 拼接正式的objectKey
                        String objectKey = path + extractFileName;
                        // 将利废入库单中的附件文件从临时目录转移到正式目录中
                        obsUtil.copyFile(objectKey, objectKeyOfTemp);
                        scfFileAttachmentInfoService.updateFilePath(fileRowId, objectKey);
                    }
                }
            }
        }

        if (rowId != null) {
            if (!rowIds.isEmpty()) {
                // 取消旧文件与记录关联
                scfFileAttachmentInfoService.updataFiledNull(rowId);
                if (rowIds.size() != 0) {
                    // 给上传的新文件添加关联编号
                    scfFileAttachmentInfoService.batchUpdateField(rowIds, rowId);
                    for (String fileRowId : rowIds) {
                        // 根据文件id获取文件的临时objectKey
                        String objectKeyOfTemp = scfFileAttachmentInfoService.getFilePath(fileRowId,null);
                        // 截取文件的名称
                        String extractFileName = obsUtil.extractFileName(objectKeyOfTemp);
                        // 拼接正式的objectKey
                        String objectKey = path + extractFileName;
                        // 将利废入库单中的附件文件从临时目录转移到正式目录中
                        obsUtil.copyFile(objectKey, objectKeyOfTemp);
                        scfFileAttachmentInfoService.updateFilePath(fileRowId, objectKey);
                    }
                }
            }
        }
        // 生成日期时间
        SimpleDateFormat datetime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String formattedDateTime = datetime.format(new Date());
        ScfOperationLogInfo scfOperationLogInfo = new ScfOperationLogInfo();
        // 根据用户id查询用户名称，重新赋值登记人字段
        List<Long> ids = new ArrayList<>();
        ids.add(Long.valueOf(scfRecyclingInInfo.getRecorder()));
        scfOperationLogInfo.setRecorder(userService.selectUserNameByIds(ids).get(0));
        scfOperationLogInfo.setOperationModule(ScfOperationLogInfoEnum.LOGISTICS.getOperation());
        scfOperationLogInfo.setOperationFunction("利废企业入库单");
        scfOperationLogInfo.setOperationType(ScfOperationLogInfoEnum.ADD.getOperation());
        scfOperationLogInfo.setOperationContent("新增一条利废企业入库单，利废企业入库单号：" + scfRecyclingInInfo.getRecyclingInNum());
        scfOperationLogInfo.setRecordDate(formattedDateTime);
        // 判断新增利废入库单是否成功
        if (isSave) {
            // 记录操作日志
            scfOperationLogInfoService.saveOperationLogInfo(scfOperationLogInfo);
            // 调用销售明细实现类中的生成销售明细记录方法
            scfSalesDetailsInfoService.generateSalesDetails(scfRecyclingInInfo.getRecyclingInNum(),scfRecyclingInInfo.getOrgCode());
        }
        return isSave;
    }

    /**
     * 批量导入接口
     * @param scfRecyclingInInfos
     * @param operatorId
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int bachSaveRecyclingInInfo(List<ScfRecyclingInInfo> scfRecyclingInInfos, String operatorId) {
        List<ScfRecyclingInInfo> scfRecyclingInInfoList = new ArrayList<>();
        for (ScfRecyclingInInfo scfRecyclingInInfo : scfRecyclingInInfos) {
            if(StringUtils.isEmpty(  scfRecyclingInInfo.getRecyclingInNum())  ){
                continue;
            }
            // 设置登记人ID
            scfRecyclingInInfo.setRecorder(operatorId);
            // 将scfRecyclingInInfoDTO传参给批量新增方法中。
            // 生成日期
            SimpleDateFormat date = new SimpleDateFormat("YYYYMMdd");
            String formatdate = date.format(new Date());
            // 生成时间
            SimpleDateFormat timeFormat = new SimpleDateFormat("HHmmss");
            String formTime = timeFormat.format(new Date());
            // 生成ROW_ID
            // 开始补充对象字段start
            // 设置默认支付状态为0.未支付
            scfRecyclingInInfo.setPaySts("0");
            // 设置默认已付金额为0
            scfRecyclingInInfo.setPaidAmount(BigDecimal.valueOf(0));
            // 获取关联的过磅单rowId
            String rowIdByWeighNum = scfRecyclingWeighInfoMapper.getRowIdByWeighNum(scfRecyclingInInfo.getWeighNum());
            // 如果关联的过磅单号不为空
            if (rowIdByWeighNum != null) {
                // 获取过磅单详情
                ScfGetRecyclingWeighDetailsVO weightDetails = scfRecyclingWeighInfoMapper.getDetails(rowIdByWeighNum);
                // 给利废企业入库单设置利废企业过磅单中的供销合同编号
                scfRecyclingInInfo.setContractNum(weightDetails.getContractNum());
                // 给利废企业入库单设置利废企业过磅单中的车牌号
                scfRecyclingInInfo.setTruckNum(weightDetails.getTruckNum());
                // 给利废企业入库单设置利废企业过磅单中的驾驶证证件号
                scfRecyclingInInfo.setLicense(weightDetails.getLicense());
            }

            // 设置记录编号
            scfRecyclingInInfo.setRowId("LFRK" + MD5Utils.md5(  scfRecyclingInInfo.getRecyclingInNum()));
            // 设置登记日期
            scfRecyclingInInfo.setRecordDate(formatdate);
            // 设置登记时间
            scfRecyclingInInfo.setRecordTime(formTime);
            // 设置初始已付金额为0
            scfRecyclingInInfo.setPaidAmount(new BigDecimal("0"));
            // 补充对象字段结束end
            // 判断是否已存在该入库单号码
            String recyclingInNum = scfRecyclingInInfo.getRecyclingInNum();
            String selectRowIdByRecyclingInNum = baseMapper.selectRowIdByRecyclingInNum(recyclingInNum);
            // 判断是否存在该入库单 不存在就导入 ，存在了 不导入
            if (selectRowIdByRecyclingInNum == null) {
                scfRecyclingInInfoList.add(scfRecyclingInInfo);
                // 生成日期时间
                SimpleDateFormat datetime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                String formattedDateTime = datetime.format(new Date());
                ScfOperationLogInfo scfOperationLogInfo = new ScfOperationLogInfo();
                // 根据用户id查询用户名称，重新赋值登记人字段
                List<Long> ids = new ArrayList<>();
                ids.add(Long.valueOf(scfRecyclingInInfo.getRecorder()));
            }
        }
        boolean saveBatch = saveBatch(scfRecyclingInInfoList);

            for (ScfRecyclingInInfo scfRecyclingInInfo : scfRecyclingInInfoList) {
                // 调用销售明细实现类中的生成销售明细记录方法
                if (scfRecyclingInInfo.getOrgCode() == null) {
                    scfSalesDetailsInfoService.generateSalesDetails(scfRecyclingInInfo.getRecyclingInNum());
                }else {
                    scfSalesDetailsInfoService.generateSalesDetails(scfRecyclingInInfo.getRecyclingInNum(),scfRecyclingInInfo.getOrgCode());
                }
            }

        return scfRecyclingInInfoList.size();
    }

    /**
     * 利废企业入库更新
     *
     * @param scfRecyclingInInfo
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateRecyclingInInfo(ScfRecyclingInInfoDTO scfRecyclingInInfo) {
        // 开始补充对象字段start
        // 补充对象字段结束end
        String rowId = scfRecyclingInInfo.getRowId();

        // 查询旧的利废企业入库单号
        ScfGetRecyclingInDetailsVO oldDetails = baseMapper.getDetails(rowId);
        String oldRecyclingInNum = oldDetails.getRecyclingInNum();

        // 接受文件的rowId数组
        List<String> rowIds = scfRecyclingInInfo.getRowIds();
        // 设置合同文件存放路径
        String path = "RCRK" + "/" + rowId + "/";
        if (rowId != null) {
            if (!rowIds.isEmpty()) {
                // 取消旧文件与记录关联
                scfFileAttachmentInfoService.updataFiledNull(rowId);
                if (rowIds.size() != 0) {
                    // 给上传的新文件添加关联编号
                    scfFileAttachmentInfoService.batchUpdateField(rowIds, rowId);
                    for (String fileRowId : rowIds) {
                        // 根据文件id获取文件的临时objectKey
                        String objectKeyOfTemp = scfFileAttachmentInfoService.getFilePath(fileRowId,null);
                        // 截取文件的名称
                        String extractFileName = obsUtil.extractFileName(objectKeyOfTemp);
                        // 拼接正式的objectKey
                        String objectKey = path + extractFileName;
                        // 将利废入库单中的附件文件从临时目录转移到正式目录中
                        obsUtil.copyFile(objectKey, objectKeyOfTemp);
                        scfFileAttachmentInfoService.updateFilePath(fileRowId, objectKey);
                    }
                }
            }
        }
        // 生成日期时间
        SimpleDateFormat datetime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String formattedDateTime = datetime.format(new Date());
        // 生成日期
        SimpleDateFormat date = new SimpleDateFormat("YYYYMMdd");
        String formatdate = date.format(new Date());
        // 生成时间
        SimpleDateFormat timeFormat = new SimpleDateFormat("HHmmss");
        String formTime = timeFormat.format(new Date());
        // 判断更新入库单时是否有旧的关联关系
        List<RecyclingInByPayment> recyclingInByPaymentsOld = baseMapper.selectRecyclingByPayment(scfRecyclingInInfo.getRecyclingInNum());
        if (recyclingInByPaymentsOld != null && !recyclingInByPaymentsOld.isEmpty()) {
            for (RecyclingInByPayment recyclingInByPayment : recyclingInByPaymentsOld) {
                // 如果存在则获取关联关系表中该支付回单使用了多少金额
                String paymentNum = recyclingInByPayment.getPaymentNum();
                // 获取当前支付回单的剩余金额
                BigDecimal remainAmountByPaymentNum = scfPaymentInfoMapper.selectAmountByPaymentNum(paymentNum);
                // 获取利废入库的使用金额
                BigDecimal useAmount = recyclingInByPayment.getUseAmount();
                // 计算使用金额加上支付回单剩余金额
                BigDecimal totalAmount = remainAmountByPaymentNum.add(useAmount);
                // 获取支付回单面值（即交易金额）
                BigDecimal amountByPaymentNum = scfPaymentInfoMapper.selectAmountByPaymentNum(paymentNum);
                // 判断使用状态
                String usageStatus;
                // 使用 compareTo 方法比较剩余金额和回单金额的大小关系
                int comparisonResult = totalAmount.compareTo(amountByPaymentNum);

                if (comparisonResult == 0) {
                    // 如果剩余金额等于回单金额，则设置为暂未使用
                    usageStatus = "0";
                } else if (comparisonResult < 0 && totalAmount.compareTo(BigDecimal.ZERO) != 0) {
                    // 如果剩余金额小于回单金额并大于0，则设置为部分使用
                    usageStatus = "1";
                } else {
                    // 如果剩余金额等于0，则设置为全部使用
                    usageStatus = "2";
                }
                // 更新支付回单中的剩余金额及使用状态
                scfPaymentInfoMapper.updateRemainAmountAndSseStsLfrkRemainAmount(paymentNum, totalAmount, usageStatus);
            }
        }
        // 清理旧的关联关系记录，然后建立新的关联关系
        baseMapper.deleteRecyclingByPayment(scfRecyclingInInfo.getRecyclingInNum());
        // 清理旧关联关系后，设置该入库单支付金额为0
        scfRecyclingInInfo.setPaidAmount(new BigDecimal("0"));
        // 初始化支付状态，默认为暂未支付
        String paymentStatus = "0";
        scfRecyclingInInfo.setPaySts(paymentStatus);
        // 开始关联支付回单
        List<RecyclingInByPayment> recyclingInByPayments = scfRecyclingInInfo.getRecyclingInByPayments();
        if (recyclingInByPayments != null) {
            // 获取支付回单关联的信息
            for (RecyclingInByPayment recyclingInByPayment : recyclingInByPayments) {
                if (recyclingInByPayment.getUseAmount() == null) {
                    throw new NullPointerException("使用金额不能为空！");
                }
                // 设置入库单号码
                recyclingInByPayment.setRecyclingInNum(scfRecyclingInInfo.getRecyclingInNum());
                recyclingInByPayment.setRecyclingInRowId(scfRecyclingInInfo.getRowId());
                recyclingInByPayment.setPaymentRowId(recyclingInByPayment.getRowId());
                // 设置支付回单关联关系的rowId为再生资源入库单的id



                recyclingInByPayment.setRowId(   "LFRK" + MD5Utils.md5(scfRecyclingInInfo.getRowId() + recyclingInByPayment.getPaymentNum()  ) );
                recyclingInByPayment.setOrgCode(scfRecyclingInInfo.getOrgCode() );
                // 获取回单使用金额
                BigDecimal useAmount = recyclingInByPayment.getUseAmount();
                // 获取初始已付金额
                BigDecimal paidAmountInit = scfRecyclingInInfo.getPaidAmount();
                // 将回单使用金额加初始已付金额运算后设置进再生入库单的已付金额中
                // 将 useAmount 和 paidAmountInit 相加
                BigDecimal totalPaidAmount = paidAmountInit.add(useAmount);
                // 设置新的已付金额
                scfRecyclingInInfo.setPaidAmount(totalPaidAmount);
                // 获取利废企业入库单的已付金额
                BigDecimal paidAmount = scfRecyclingInInfo.getPaidAmount();
                // 获取利废企业入库的总金额
                BigDecimal amount = scfRecyclingInInfo.getAmount();
                // 判断支付状态
                if (paidAmount.compareTo(BigDecimal.ZERO) > 0) {
                    if (paidAmount.compareTo(amount) < 0) {
                        // 如果已付小于总额，则设置为部分支付
                        paymentStatus = "1";
                    } else if (paidAmount.compareTo(amount) == 0) {
                        // 如果已付等于总额，则设置为全部支付
                        paymentStatus = "2";
                    } else if (totalPaidAmount.compareTo(scfRecyclingInInfo.getSettlementAmount() ) >0) {
                        // 如果已付金额大于入库单金额，则抛出异常
                        throw new RuntimeException("支付回单输入的使用金额超过入库单金额！");
                    }
                    // 如果已付总额等于0，保持为暂未支付
                }
                // 将支付状态设置到再生资源入库单
                scfRecyclingInInfo.setPaySts(paymentStatus);
                baseMapper.saveRecyclingByPayment(recyclingInByPayment);
                // 获取当前支付回单的当前剩余金额
                BigDecimal remainAmountByPaymentNum = scfPaymentInfoMapper.selectAmountByPaymentNum(recyclingInByPayment.getPaymentNum());
                // 将上一步获取到的金额加上新使用的金额
                // 将 remainAmountByPaymentNum 和 useAmount 相减
                BigDecimal totalAmount = remainAmountByPaymentNum.subtract(useAmount);

                // 获取支付回单的总面值
                BigDecimal amountByPaymentNum = scfPaymentInfoMapper.selectAmountByPaymentNum(recyclingInByPayment.getPaymentNum());
                // 判断
                String usageStatus;
                // 使用 compareTo 方法比较剩余金额和回单金额的大小关系
                int comparisonResult = totalAmount.compareTo(amountByPaymentNum);

                if (comparisonResult == 0) {
                    // 如果剩余金额等于回单金额，则设置为暂未使用
                    usageStatus = "0";
                } else if (comparisonResult < 0 && totalAmount.compareTo(BigDecimal.ZERO) != 0) {
                    // 如果剩余金额小于回单金额并大于0，则设置为部分使用
                    usageStatus = "1";
                } else {
                    // 如果剩余金额等于0，则设置为全部使用
                    usageStatus = "2";
                }
                // 同步更新对应回单的剩余金额及支付状态
                scfPaymentInfoMapper.updateRemainAmountAndSseStsLfrkRemainAmount(recyclingInByPayment.getPaymentNum(), totalAmount, usageStatus);
            }
        }
        boolean update = updateById(scfRecyclingInInfo);
        // 记录操作日志
        ScfOperationLogInfo scfOperationLogInfo = new ScfOperationLogInfo();
        scfOperationLogInfo.setRowId("Log" + formatdate + formTime + localCacheIdGenerator.nextId());
        // 根据用户id查询用户名称，重新赋值登记人字段
        List<Long> ids = new ArrayList<>();
        ids.add(Long.valueOf(scfRecyclingInInfo.getRecorder()));
        scfOperationLogInfo.setRecorder(userService.selectUserNameByIds(ids).get(0));
        scfOperationLogInfo.setOperationModule(ScfOperationLogInfoEnum.LOGISTICS.getOperation());
        scfOperationLogInfo.setOperationFunction("利废企业入库单");
        scfOperationLogInfo.setOperationType(ScfOperationLogInfoEnum.UPDATE.getOperation());
        scfOperationLogInfo.setOperationContent("更新一条利废企业入库单，利废企业入库单号：" + scfRecyclingInInfo.getRecyclingInNum());
        scfOperationLogInfo.setRecordDate(formattedDateTime);
        // 判断利废入库单新增是否成功
        if (update) {
            // 成功则记录对应操作日志
            scfOperationLogInfoService.saveOperationLogInfo(scfOperationLogInfo);
            // 调用销售明细实现类中的生成销售明细记录方法
            String selectRowIdByRecyclingInNum= scfSalesDetailsInfoMapper.selectRowIdByRecyclingInNum(oldRecyclingInNum);
            if (selectRowIdByRecyclingInNum != null) {
                scfSalesDetailsInfoService.update(oldRecyclingInNum, rowId,scfRecyclingInInfo.getOrgCode());
            }else {
                // 出现极端情况，入库单不存在对应的销售明细记录-则调用销售明细生成方法，生成一条明细数据。
                scfSalesDetailsInfoService.generateSalesDetails(oldRecyclingInNum,scfRecyclingInInfo.getOrgCode());
            }
        }
        return update;
    }

    /**
     * 利废企业入库批量导入
     *
     * @param operatorId
     * @param file
     * @return
     * @throws IOException
     */
    @Override
    public List<ScfRecyclingInInfo> batchSaveRecyclingInInfo(String operatorId, MultipartFile file) throws IOException {
        // 获取文件的Base64编码
        byte[] fileBytes = file.getBytes();
        // 解析excel文件获取数据集合
        List<ScfRecyclingInInfo> scfRecyclingInInfos = ExcelUtil.readExcel(fileBytes, ScfRecyclingInInfo.class, "利废企业入库单", 3);
        log.info("数据集合为：{}", scfRecyclingInInfos);
        return scfRecyclingInInfos;
    }


    /**
     * 再生资源信息删除
     * @param ids
     * @return
     */
    @Override
    public Boolean deleteByIds(String[] ids) {
        return this.baseMapper.deleteByIds(ids);
    }
}
